package com.hfb.mashibing.alip8.juc.c020_01_interview.A1B2C3;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 *  互联网一线大厂面试题：
 *      徒手写出：2个不同的线程，交替输出A1B2C3。。。
 *
 * 线程排序问题
 * 思路：利用 等待队列(ReentrantLock) 和 volatile 的 flag，
 *      再利用一个条件队列分别依次遍历字母队列和数字队列
 *
 */
public class A1B2C3ReentrantLock {
    private static char[] charsLetter = "ABCDEFGHI".toCharArray();
    private static char[] charsNumber = "123456789".toCharArray();


    static ReentrantLock reentrantLock = new ReentrantLock();
    static volatile boolean flag = true;

    public static void main(String[] args) {
        Condition condition = reentrantLock.newCondition();
        new Thread(()->{
            // 利用 flag 保证线程1 在线程2 之前执行
            while (!flag){}
            flag = false;
            try {
                // t1先获取锁
                reentrantLock.lock();
                for (int i = 0; i < charsLetter.length; i++) {
                    // 将等待队列线程同步到CLH队列
                    condition.signal();
                    System.out.print(charsLetter[i]);
                    // t1放倒等待队列，并唤醒CLH队列head的下一个node代表的线程唤醒
                    condition.await();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 为什么加这一行代码？
                // t2是在打印F6的6以后，通过await()将t2存放到等待队列中，并唤醒t1线程，
                // 故此时CLH队列总只有t1，而线程被唤醒只能在CLH队列中，这段代码就是线程
                // 从等待队列中转移到CLH队列，通过unlock将t2唤醒
                condition.signal();
                reentrantLock.unlock();
            }
        },"t1").start();

        new Thread(()->{
            // 利用 flag 保证线程1 在线程2 之前执行
            while (flag){}
            try {
                // 线程1先获取锁
                reentrantLock.lock();
                for (int i = 0; i < charsNumber.length; i++) {
                    // 将等待队列线程同步到CLH队列
                    condition.signal();
                    System.out.print(charsNumber[i]);
                    condition.await();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 为什么加这一行代码？
                // t2是在打印F6的6以后，通过await()将t2存放到等待队列中，并唤醒t1线程，
                // 故此时CLH队列总只有t1，而线程被唤醒只能在CLH队列中，这段代码就是线程
                // 从等待队列中转移到CLH队列，通过unlock将t2唤醒
//                condition.signal();
                reentrantLock.unlock();
            }
            System.out.println();
        },"t1").start();

    }
}
